home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / calc202a.lha / calc-2.02a / calc-graph.el < prev    next >
Lisp/Scheme  |  1993-06-01  |  47KB  |  1,494 lines

  1. ;; Calculator for GNU Emacs, part II [calc-graph.el]
  2. ;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
  3. ;; Written by Dave Gillespie, daveg@synaptics.com.
  4.  
  5. ;; This file is part of GNU Emacs.
  6.  
  7. ;; GNU Emacs is distributed in the hope that it will be useful,
  8. ;; but WITHOUT ANY WARRANTY.  No author or distributor
  9. ;; accepts responsibility to anyone for the consequences of using it
  10. ;; or for whether it serves any particular purpose or works at all,
  11. ;; unless he says so in writing.  Refer to the GNU Emacs General Public
  12. ;; License for full details.
  13.  
  14. ;; Everyone is granted permission to copy, modify and redistribute
  15. ;; GNU Emacs, but only under the conditions described in the
  16. ;; GNU Emacs General Public License.   A copy of this license is
  17. ;; supposed to have been given to you along with GNU Emacs so you
  18. ;; can know your rights and responsibilities.  It should be in a
  19. ;; file named COPYING.  Among other things, the copyright notice
  20. ;; and this notice must be preserved on all copies.
  21.  
  22.  
  23.  
  24. ;; This file is autoloaded from calc-ext.el.
  25. (require 'calc-ext)
  26.  
  27. (require 'calc-macs)
  28.  
  29. (defun calc-Need-calc-graph () nil)
  30.  
  31.  
  32. ;;; Graphics
  33.  
  34. ;;; Note that some of the following initial values also occur in calc.el.
  35. (defvar calc-gnuplot-tempfile "/tmp/calc")
  36.  
  37. (defvar calc-gnuplot-default-device "default")
  38. (defvar calc-gnuplot-default-output "STDOUT")
  39. (defvar calc-gnuplot-print-device "postscript")
  40. (defvar calc-gnuplot-print-output "auto")
  41. (defvar calc-gnuplot-keep-outfile nil)
  42. (defvar calc-gnuplot-version nil)
  43.  
  44. (defvar calc-gnuplot-display (getenv "DISPLAY"))
  45. (defvar calc-gnuplot-geometry nil)
  46.  
  47. (defvar calc-graph-default-resolution 15)
  48. (defvar calc-graph-default-resolution-3d 5)
  49. (defvar calc-graph-default-precision 5)
  50.  
  51. (defvar calc-gnuplot-buffer nil)
  52. (defvar calc-gnuplot-input nil)
  53.  
  54. (defvar calc-gnuplot-last-error-pos 1)
  55. (defvar calc-graph-last-device nil)
  56. (defvar calc-graph-last-output nil)
  57. (defvar calc-graph-file-cache nil)
  58. (defvar calc-graph-var-cache nil)
  59. (defvar calc-graph-data-cache nil)
  60. (defvar calc-graph-data-cache-limit 10)
  61.  
  62. (defun calc-graph-fast (many)
  63.   (interactive "P")
  64.   (let ((calc-graph-no-auto-view t))
  65.     (calc-graph-delete t)
  66.     (calc-graph-add many)
  67.     (calc-graph-plot nil))
  68. )
  69.  
  70. (defun calc-graph-fast-3d (many)
  71.   (interactive "P")
  72.   (let ((calc-graph-no-auto-view t))
  73.     (calc-graph-delete t)
  74.     (calc-graph-add-3d many)
  75.     (calc-graph-plot nil))
  76. )
  77.  
  78. (defun calc-graph-delete (all)
  79.   (interactive "P")
  80.   (calc-wrapper
  81.    (calc-graph-init)
  82.    (save-excursion
  83.      (set-buffer calc-gnuplot-input)
  84.      (and (calc-graph-find-plot t all)
  85.       (progn
  86.         (if (looking-at "s?plot")
  87.         (progn
  88.           (setq calc-graph-var-cache nil)
  89.           (delete-region (point) (point-max)))
  90.           (delete-region (point) (1- (point-max)))))))
  91.    (calc-graph-view-commands))
  92. )
  93.  
  94. (defun calc-graph-find-plot (&optional before all)
  95.   (goto-char (point-min))
  96.   (and (re-search-forward "^s?plot[ \t]+" nil t)
  97.        (let ((beg (point)))
  98.      (goto-char (point-max))
  99.      (if (or all
  100.          (not (search-backward "," nil t))
  101.          (< (point) beg))
  102.          (progn
  103.            (goto-char beg)
  104.            (if before
  105.            (beginning-of-line)))
  106.        (or before
  107.            (re-search-forward ",[ \t]+")))
  108.      t))
  109. )
  110.  
  111. (defun calc-graph-add (many)
  112.   (interactive "P")
  113.   (calc-wrapper
  114.    (calc-graph-init)
  115.    (cond ((null many)
  116.       (calc-graph-add-curve (calc-graph-lookup (calc-top-n 2))
  117.                 (calc-graph-lookup (calc-top-n 1))))
  118.      ((or (consp many) (eq many 0))
  119.       (let ((xdata (calc-graph-lookup (calc-top-n 2)))
  120.         (ylist (calc-top-n 1)))
  121.         (or (eq (car-safe ylist) 'vec)
  122.         (error "Y argument must be a vector"))
  123.         (while (setq ylist (cdr ylist))
  124.           (calc-graph-add-curve xdata (calc-graph-lookup (car ylist))))))
  125.      ((> (setq many (prefix-numeric-value many)) 0)
  126.       (let ((xdata (calc-graph-lookup (calc-top-n (1+ many)))))
  127.         (while (> many 0)
  128.           (calc-graph-add-curve xdata
  129.                     (calc-graph-lookup (calc-top-n many)))
  130.           (setq many (1- many)))))
  131.      (t
  132.       (let (pair)
  133.         (setq many (- many))
  134.         (while (> many 0)
  135.           (setq pair (calc-top-n many))
  136.           (or (and (eq (car-safe pair) 'vec)
  137.                (= (length pair) 3))
  138.           (error "Argument must be an [x,y] vector"))
  139.           (calc-graph-add-curve (calc-graph-lookup (nth 1 pair))
  140.                     (calc-graph-lookup (nth 2 pair)))
  141.           (setq many (1- many))))))
  142.    (calc-graph-view-commands))
  143. )
  144.  
  145. (defun calc-graph-add-3d (many)
  146.   (interactive "P")
  147.   (calc-wrapper
  148.    (calc-graph-init)
  149.    (cond ((null many)
  150.       (calc-graph-add-curve (calc-graph-lookup (calc-top-n 3))
  151.                 (calc-graph-lookup (calc-top-n 2))
  152.                 (calc-graph-lookup (calc-top-n 1))))
  153.      ((or (consp many) (eq many 0))
  154.       (let ((xdata (calc-graph-lookup (calc-top-n 3)))
  155.         (ydata (calc-graph-lookup (calc-top-n 2)))
  156.         (zlist (calc-top-n 1)))
  157.         (or (eq (car-safe zlist) 'vec)
  158.         (error "Z argument must be a vector"))
  159.         (while (setq zlist (cdr zlist))
  160.           (calc-graph-add-curve xdata ydata
  161.                     (calc-graph-lookup (car zlist))))))
  162.      ((> (setq many (prefix-numeric-value many)) 0)
  163.       (let ((xdata (calc-graph-lookup (calc-top-n (+ many 2))))
  164.         (ydata (calc-graph-lookup (calc-top-n (+ many 1)))))
  165.         (while (> many 0)
  166.           (calc-graph-add-curve xdata ydata
  167.                     (calc-graph-lookup (calc-top-n many)))
  168.           (setq many (1- many)))))
  169.      (t
  170.       (let (curve)
  171.         (setq many (- many))
  172.         (while (> many 0)
  173.           (setq curve (calc-top-n many))
  174.           (or (and (eq (car-safe curve) 'vec)
  175.                (= (length curve) 4))
  176.           (error "Argument must be an [x,y,z] vector"))
  177.           (calc-graph-add-curve (calc-graph-lookup (nth 1 curve))
  178.                     (calc-graph-lookup (nth 2 curve))
  179.                     (calc-graph-lookup (nth 3 curve)))
  180.           (setq many (1- many))))))
  181.    (calc-graph-view-commands))
  182. )
  183.  
  184. (defun calc-graph-add-curve (xdata ydata &optional zdata)
  185.   (let ((num (calc-graph-count-curves))
  186.     (pstyle (calc-var-value 'var-PointStyles))
  187.     (lstyle (calc-var-value 'var-LineStyles)))
  188.     (save-excursion
  189.       (set-buffer calc-gnuplot-input)
  190.       (goto-char (point-min))
  191.       (if (re-search-forward (if zdata "^plot[ \t]" "^splot[ \t]")
  192.                  nil t)
  193.       (error "Can't mix 2d and 3d curves on one graph"))
  194.       (if (re-search-forward "^s?plot[ \t]" nil t)
  195.       (progn
  196.         (end-of-line)
  197.         (insert ", "))
  198.     (goto-char (point-max))
  199.     (or (eq (preceding-char) ?\n)
  200.         (insert "\n"))
  201.     (insert (if zdata "splot" "plot") " \n")
  202.     (forward-char -1))
  203.       (insert "{" (symbol-name (nth 1 xdata))
  204.           ":" (symbol-name (nth 1 ydata)))
  205.       (if zdata
  206.       (insert ":" (symbol-name (nth 1 zdata))))
  207.       (insert "} "
  208.           "title \"" (symbol-name (nth 1 ydata)) "\" "
  209.           "with dots")
  210.       (setq pstyle (and (eq (car-safe pstyle) 'vec) (nth (1+ num) pstyle)))
  211.       (setq lstyle (and (eq (car-safe lstyle) 'vec) (nth (1+ num) lstyle)))
  212.       (calc-graph-set-styles
  213.        (or (and (Math-num-integerp lstyle) (math-trunc lstyle))
  214.        0)
  215.        (or (and (Math-num-integerp pstyle) (math-trunc pstyle))
  216.        (if (eq (car-safe (calc-var-value (nth 2 ydata))) 'vec)
  217.            0 -1)))))
  218. )
  219.  
  220. (defun calc-graph-lookup (thing)
  221.   (if (and (eq (car-safe thing) 'var)
  222.        (calc-var-value (nth 2 thing)))
  223.       thing
  224.     (let ((found (assoc thing calc-graph-var-cache)))
  225.       (or found
  226.       (progn
  227.         (setq varname (concat "PlotData"
  228.                   (int-to-string
  229.                    (1+ (length calc-graph-var-cache))))
  230.           var (list 'var (intern varname)
  231.                 (intern (concat "var-" varname)))
  232.           found (cons thing var)
  233.           calc-graph-var-cache (cons found calc-graph-var-cache))
  234.         (set (nth 2 var) thing)))
  235.       (cdr found)))
  236. )
  237.  
  238. (defun calc-graph-juggle (arg)
  239.   (interactive "p")
  240.   (calc-graph-init)
  241.   (save-excursion
  242.     (set-buffer calc-gnuplot-input)
  243.     (if (< arg 0)
  244.     (let ((num (calc-graph-count-curves)))
  245.       (if (> num 0)
  246.           (while (< arg 0)
  247.         (setq arg (+ arg num))))))
  248.     (while (>= (setq arg (1- arg)) 0)
  249.       (calc-graph-do-juggle)))
  250. )
  251.  
  252. (defun calc-graph-count-curves ()
  253.   (save-excursion
  254.     (set-buffer calc-gnuplot-input)
  255.     (if (re-search-forward "^s?plot[ \t]" nil t)
  256.     (let ((num 1))
  257.       (goto-char (point-min))
  258.       (while (search-forward "," nil t)
  259.         (setq num (1+ num)))
  260.       num)
  261.       0))
  262. )
  263.  
  264. (defun calc-graph-do-juggle ()
  265.   (let (base)
  266.     (and (calc-graph-find-plot t t)
  267.      (progn
  268.        (setq base (point))
  269.        (calc-graph-find-plot t nil)
  270.        (or (eq base (point))
  271.            (let ((str (buffer-substring (+ (point) 2) (1- (point-max)))))
  272.          (delete-region (point) (1- (point-max)))
  273.          (goto-char (+ base 5))
  274.          (insert str ", "))))))
  275. )
  276.  
  277. (defun calc-graph-print (flag)
  278.   (interactive "P")
  279.   (calc-graph-plot flag t)
  280. )
  281.  
  282. (defun calc-graph-plot (flag &optional printing)
  283.   (interactive "P")
  284.   (calc-slow-wrapper
  285.    (let ((calcbuf (current-buffer))
  286.      (tempbuf (get-buffer-create "*Gnuplot Temp-2*"))
  287.      (tempbuftop 1)
  288.      (tempoutfile nil)
  289.      (curve-num 0)
  290.      (refine (and flag (> (prefix-numeric-value flag) 0)))
  291.      (recompute (and flag (< (prefix-numeric-value flag) 0)))
  292.      (surprise-splot nil)
  293.      (tty-output nil)
  294.      cache-env is-splot device output resolution precision samples-pos)
  295.      (or (boundp 'calc-graph-prev-kill-hook)
  296.      (progn
  297.        (setq calc-graph-prev-kill-hook kill-emacs-hook)
  298.        (setq kill-emacs-hook 'calc-graph-kill-hook)))
  299.      (save-excursion
  300.        (calc-graph-init)
  301.        (set-buffer tempbuf)
  302.        (erase-buffer)
  303.        (set-buffer calc-gnuplot-input)
  304.        (goto-char (point-min))
  305.        (setq is-splot (re-search-forward "^splot[ \t]" nil t))
  306.        (let ((str (buffer-string))
  307.          (ver calc-gnuplot-version))
  308.      (set-buffer (get-buffer-create "*Gnuplot Temp*"))
  309.      (erase-buffer)
  310.      (insert "# (Note: This is a temporary copy---do not edit!)\n")
  311.      (if (>= ver 2)
  312.          (insert "set noarrow\nset nolabel\n"
  313.              "set autoscale xy\nset nologscale xy\n"
  314.              "set xlabel\nset ylabel\nset title\n"
  315.              "set noclip points\nset clip one\nset clip two\n"
  316.              "set format \"%g\"\nset tics\nset xtics\nset ytics\n"
  317.              "set data style linespoints\n"
  318.              "set nogrid\nset nokey\nset nopolar\n"))
  319.      (if (>= ver 3)
  320.          (insert "set surface\nset nocontour\n"
  321.              "set " (if is-splot "" "no") "parametric\n"
  322.              "set notime\nset border\nset ztics\nset zeroaxis\n"
  323.              "set view 60,30,1,1\nset offsets 0,0,0,0\n"))
  324.      (setq samples-pos (point))
  325.      (insert "\n\n" str))
  326.        (goto-char (point-min))
  327.        (if is-splot
  328.        (if refine
  329.            (error "This option works only for 2d plots")
  330.          (setq recompute t)))
  331.        (let ((calc-gnuplot-input (current-buffer))
  332.          (calc-graph-no-auto-view t))
  333.      (if printing
  334.          (setq device calc-gnuplot-print-device
  335.            output calc-gnuplot-print-output)
  336.        (setq device (calc-graph-find-command "terminal")
  337.          output (calc-graph-find-command "output"))
  338.        (or device
  339.            (setq device calc-gnuplot-default-device))
  340.        (if output
  341.            (setq output (car (read-from-string output)))
  342.          (setq output calc-gnuplot-default-output)))
  343.      (if (or (equal device "") (equal device "default"))
  344.          (setq device (if printing
  345.                   "postscript"
  346.                 (if (or (eq window-system 'x) (getenv "DISPLAY"))
  347.                 "x11"
  348.                   (if (>= calc-gnuplot-version 3)
  349.                   "dumb" "postscript")))))
  350.      (if (equal device "dumb")
  351.          (setq device (format "dumb %d %d"
  352.                   (1- (screen-width)) (1- (screen-height)))))
  353.      (if (equal device "big")
  354.          (setq device (format "dumb %d %d"
  355.                   (* 4 (- (screen-width) 3))
  356.                   (* 4 (- (screen-height) 3)))))
  357.      (if (stringp output)
  358.          (if (or (equal output "auto")
  359.              (and (equal output "tty") (setq tty-output t)))
  360.          (setq tempoutfile (calc-temp-file-name -1)
  361.                output tempoutfile))
  362.        (setq output (eval output)))
  363.      (or (equal device calc-graph-last-device)
  364.          (progn
  365.            (setq calc-graph-last-device device)
  366.            (calc-gnuplot-command "set terminal" device)))
  367.      (or (equal output calc-graph-last-output)
  368.          (progn
  369.            (setq calc-graph-last-output output)
  370.            (calc-gnuplot-command "set output"
  371.                      (if (equal output "STDOUT")
  372.                      ""
  373.                        (prin1-to-string output)))))
  374.      (setq resolution (calc-graph-find-command "samples"))
  375.      (if resolution
  376.          (setq resolution (string-to-int resolution))
  377.        (setq resolution (if is-splot
  378.                 calc-graph-default-resolution-3d
  379.                   calc-graph-default-resolution)))
  380.      (setq precision (calc-graph-find-command "precision"))
  381.      (if precision
  382.          (setq precision (string-to-int precision))
  383.        (setq precision calc-graph-default-precision))
  384.      (calc-graph-set-command "terminal")
  385.      (calc-graph-set-command "output")
  386.      (calc-graph-set-command "samples")
  387.      (calc-graph-set-command "precision"))
  388.        (goto-char samples-pos)
  389.        (insert "set samples " (int-to-string (max (if is-splot 20 200)
  390.                           (+ 5 resolution))) "\n")
  391.        (while (re-search-forward "{\\*[^}]+}[^,\n]*" nil t)
  392.      (delete-region (match-beginning 0) (match-end 0))
  393.      (if (looking-at ",")
  394.          (delete-char 1)
  395.        (while (memq (preceding-char) '(?\ ?\t))
  396.          (forward-char -1))
  397.        (if (eq (preceding-char) ?\,)
  398.            (delete-backward-char 1))))
  399.        (save-excursion
  400.      (set-buffer calcbuf)
  401.      (setq cache-env (list calc-angle-mode
  402.                    calc-complex-mode
  403.                    calc-simplify-mode
  404.                    calc-infinite-mode
  405.                    calc-word-size
  406.                    precision is-splot))
  407.      (if (and (not recompute)
  408.           (equal (cdr (car calc-graph-data-cache)) cache-env))
  409.          (while (> (length calc-graph-data-cache)
  410.                calc-graph-data-cache-limit)
  411.            (setcdr calc-graph-data-cache
  412.                (cdr (cdr calc-graph-data-cache))))
  413.        (setq calc-graph-data-cache (list (cons nil cache-env)))))
  414.        (calc-graph-find-plot t t)
  415.        (while (re-search-forward
  416.            (if is-splot
  417.            "{\\([^{}:\n]+\\):\\([^{}:\n]+\\):\\([^{}:\n]+\\)}"
  418.          "{\\([^{}:\n]+\\)\\(:\\)\\([^{}:\n]+\\)}")
  419.            nil t)
  420.      (setq curve-num (1+ curve-num))
  421.      (let* ((xname (buffer-substring (match-beginning 1) (match-end 1)))
  422.         (xvar (intern (concat "var-" xname)))
  423.         (xvalue (math-evaluate-expr (calc-var-value xvar)))
  424.         (y3name (and is-splot
  425.                  (buffer-substring (match-beginning 2)
  426.                            (match-end 2))))
  427.         (y3var (and is-splot (intern (concat "var-" y3name))))
  428.         (y3value (and is-splot (calc-var-value y3var)))
  429.         (yname (buffer-substring (match-beginning 3) (match-end 3)))
  430.         (yvar (intern (concat "var-" yname)))
  431.         (yvalue (calc-var-value yvar))
  432.         filename)
  433.        (delete-region (match-beginning 0) (match-end 0))
  434.        (setq filename (calc-temp-file-name curve-num))
  435.        (save-excursion
  436.          (set-buffer calcbuf)
  437.          (let (tempbuftop
  438.            (xp xvalue)
  439.            (yp yvalue)
  440.            (zp nil)
  441.            (xlow nil) (xhigh nil) (y3low nil) (y3high nil)
  442.            xvec xval xstep var-DUMMY
  443.            y3vec y3val y3step var-DUMMY2 (zval nil)
  444.            yvec yval ycache ycacheptr yvector
  445.            numsteps numsteps3
  446.            (keep-file (and (not is-splot) (file-exists-p filename)))
  447.            (stepcount 0)
  448.            (calc-symbolic-mode nil)
  449.            (calc-prefer-frac nil)
  450.            (calc-internal-prec (max 3 precision))
  451.            (calc-simplify-mode (and (not (memq calc-simplify-mode
  452.                                '(none num)))
  453.                         calc-simplify-mode))
  454.            (blank t)
  455.            (non-blank nil)
  456.            (math-working-step 0)
  457.            (math-working-step-2 nil))
  458.            (save-excursion
  459.          (if is-splot
  460.              (calc-graph-compute-3d)
  461.            (calc-graph-compute-2d))
  462.          (set-buffer tempbuf)
  463.          (goto-char (point-max))
  464.          (insert "\n" xname)
  465.          (if is-splot
  466.              (insert ":" y3name))
  467.          (insert ":" yname "\n\n")
  468.          (setq tempbuftop (point))
  469.          (let ((calc-group-digits nil)
  470.                (calc-leading-zeros nil)
  471.                (calc-number-radix 10)
  472.                (entry (and (not is-splot)
  473.                    (list xp yp xhigh numsteps))))
  474.            (or (equal entry
  475.                   (nth 1 (nth (1+ curve-num)
  476.                       calc-graph-file-cache)))
  477.                (setq keep-file nil))
  478.            (setcar (cdr (nth (1+ curve-num) calc-graph-file-cache))
  479.                entry)
  480.            (or keep-file
  481.                (calc-graph-format-data)))
  482.          (or keep-file
  483.              (progn
  484.                (or non-blank
  485.                (error "No valid data points for %s:%s"
  486.                   xname yname))
  487.                (write-region tempbuftop (point-max) filename
  488.                      nil 'quiet))))))
  489.        (insert (prin1-to-string filename))))
  490.        (if surprise-splot
  491.        (setcdr cache-env nil))
  492.        (if (= curve-num 0)
  493.        (progn
  494.          (calc-gnuplot-command "clear")
  495.          (calc-clear-command-flag 'clear-message)
  496.          (message "No data to plot!"))
  497.      (setq calc-graph-data-cache-limit (max curve-num
  498.                         calc-graph-data-cache-limit)
  499.            filename (calc-temp-file-name 0))
  500.      (write-region (point-min) (point-max) filename nil 'quiet)
  501.      (calc-gnuplot-command "load" (prin1-to-string filename))
  502.      (or (equal output "STDOUT")
  503.          calc-gnuplot-keep-outfile
  504.          (progn   ; need to close the output file before printing/plotting
  505.            (setq calc-graph-last-output "STDOUT")
  506.            (calc-gnuplot-command "set output")))
  507.      (let ((command (if printing
  508.                 calc-gnuplot-print-command
  509.               (or calc-gnuplot-plot-command
  510.                   (and (string-match "^dumb" device)
  511.                    'calc-graph-show-dumb)
  512.                   (and tty-output
  513.                    'calc-graph-show-tty)))))
  514.        (if command
  515.            (if (stringp command)
  516.            (calc-gnuplot-command
  517.             "!" (format command
  518.                 (or tempoutfile
  519.                     calc-gnuplot-print-output)))
  520.          (if (symbolp command)
  521.              (funcall command output)
  522.            (eval command)))))))))
  523. )
  524.  
  525. (defun calc-graph-compute-2d ()
  526.   (if (setq yvec (eq (car-safe yvalue) 'vec))
  527.       (if (= (setq numsteps (1- (length yvalue))) 0)
  528.       (error "Can't plot an empty vector")
  529.     (if (setq xvec (eq (car-safe xvalue) 'vec))
  530.         (or (= (1- (length xvalue)) numsteps)
  531.         (error "%s and %s have different lengths" xname yname))
  532.       (if (and (eq (car-safe xvalue) 'intv)
  533.            (math-constp xvalue))
  534.           (setq xstep (math-div (math-sub (nth 3 xvalue)
  535.                           (nth 2 xvalue))
  536.                     (1- numsteps))
  537.             xvalue (nth 2 xvalue))
  538.         (if (math-realp xvalue)
  539.         (setq xstep 1)
  540.           (error "%s is not a suitable basis for %s" xname yname)))))
  541.     (or (math-realp yvalue)
  542.     (let ((arglist nil))
  543.       (setq yvalue (math-evaluate-expr yvalue))
  544.       (calc-default-formula-arglist yvalue)
  545.       (or arglist
  546.           (error "%s does not contain any unassigned variables" yname))
  547.       (and (cdr arglist)
  548.            (error "%s contains more than one variable: %s"
  549.               yname arglist))
  550.       (setq yvalue (math-expr-subst yvalue
  551.                     (math-build-var-name (car arglist))
  552.                     '(var DUMMY var-DUMMY)))))
  553.     (setq ycache (assoc yvalue calc-graph-data-cache))
  554.     (delq ycache calc-graph-data-cache)
  555.     (nconc calc-graph-data-cache
  556.        (list (or ycache (setq ycache (list yvalue)))))
  557.     (if (and (not (setq xvec (eq (car-safe xvalue) 'vec)))
  558.          refine (cdr (cdr ycache)))
  559.     (calc-graph-refine-2d)
  560.       (calc-graph-recompute-2d)))
  561. )
  562.  
  563. (defun calc-graph-refine-2d ()
  564.   (setq keep-file nil
  565.     ycacheptr (cdr ycache))
  566.   (if (and (setq xval (calc-graph-find-command "xrange"))
  567.        (string-match "\\`\\[\\([0-9.eE+-]*\\):\\([0-9.eE+-]*\\)\\]\\'"
  568.              xval))
  569.       (let ((b2 (match-beginning 2))
  570.         (e2 (match-end 2)))
  571.     (setq xlow (math-read-number (substring xval
  572.                         (match-beginning 1)
  573.                         (match-end 1)))
  574.           xhigh (math-read-number (substring xval b2 e2))))
  575.     (if xlow
  576.     (while (and (cdr ycacheptr)
  577.             (Math-lessp (car (nth 1 ycacheptr)) xlow))
  578.       (setq ycacheptr (cdr ycacheptr)))))
  579.   (setq math-working-step-2 (1- (length ycacheptr)))
  580.   (while (and (cdr ycacheptr)
  581.           (or (not xhigh)
  582.           (Math-lessp (car (car ycacheptr)) xhigh)))
  583.     (setq var-DUMMY (math-div (math-add (car (car ycacheptr))
  584.                     (car (nth 1 ycacheptr)))
  585.                   2)
  586.       math-working-step (1+ math-working-step)
  587.       yval (math-evaluate-expr yvalue))
  588.     (setcdr ycacheptr (cons (cons var-DUMMY yval)
  589.                 (cdr ycacheptr)))
  590.     (setq ycacheptr (cdr (cdr ycacheptr))))
  591.   (setq yp ycache
  592.     numsteps 1000000)
  593. )
  594.  
  595. (defun calc-graph-recompute-2d ()
  596.   (setq ycacheptr ycache)
  597.   (if xvec
  598.       (setq numsteps (1- (length xvalue))
  599.         yvector nil)
  600.     (if (and (eq (car-safe xvalue) 'intv)
  601.          (math-constp xvalue))
  602.     (setq numsteps resolution
  603.           yp nil
  604.           xlow (nth 2 xvalue)
  605.           xhigh (nth 3 xvalue)
  606.           xstep (math-div (math-sub xhigh xlow)
  607.                   (1- numsteps))
  608.           xvalue (nth 2 xvalue))
  609.       (error "%s is not a suitable basis for %s"
  610.          xname yname)))
  611.   (setq math-working-step-2 numsteps)
  612.   (while (>= (setq numsteps (1- numsteps)) 0)
  613.     (setq math-working-step (1+ math-working-step))
  614.     (if xvec
  615.     (progn
  616.       (setq xp (cdr xp)
  617.         xval (car xp))
  618.       (and (not (eq ycacheptr ycache))
  619.            (consp (car ycacheptr))
  620.            (not (Math-lessp (car (car ycacheptr)) xval))
  621.            (setq ycacheptr ycache)))
  622.       (if (= numsteps 0)
  623.       (setq xval xhigh)   ; avoid cumulative roundoff
  624.     (setq xval xvalue
  625.           xvalue (math-add xvalue xstep))))
  626.     (while (and (cdr ycacheptr)
  627.         (Math-lessp (car (nth 1 ycacheptr)) xval))
  628.       (setq ycacheptr (cdr ycacheptr)))
  629.     (or (and (cdr ycacheptr)
  630.          (Math-equal (car (nth 1 ycacheptr)) xval))
  631.     (progn
  632.       (setq keep-file nil
  633.         var-DUMMY xval)
  634.       (setcdr ycacheptr (cons (cons xval (math-evaluate-expr yvalue))
  635.                   (cdr ycacheptr)))))
  636.     (setq ycacheptr (cdr ycacheptr))
  637.     (if xvec
  638.     (setq yvector (cons (cdr (car ycacheptr)) yvector))
  639.       (or yp (setq yp ycacheptr))))
  640.   (if xvec
  641.       (setq xp xvalue
  642.         yvec t
  643.         yp (cons 'vec (nreverse yvector))
  644.         numsteps (1- (length xp)))
  645.     (setq numsteps 1000000))
  646. )
  647.  
  648. (defun calc-graph-compute-3d ()
  649.   (if (setq yvec (eq (car-safe yvalue) 'vec))
  650.       (if (math-matrixp yvalue)
  651.       (progn
  652.         (setq numsteps (1- (length yvalue))
  653.           numsteps3 (1- (length (nth 1 yvalue))))
  654.         (if (eq (car-safe xvalue) 'vec)
  655.         (or (= (1- (length xvalue)) numsteps)
  656.             (error "%s has wrong length" xname))
  657.           (if (and (eq (car-safe xvalue) 'intv)
  658.                (math-constp xvalue))
  659.           (setq xvalue (calcFunc-index numsteps
  660.                            (nth 2 xvalue)
  661.                            (math-div
  662.                         (math-sub (nth 3 xvalue)
  663.                               (nth 2 xvalue))
  664.                         (1- numsteps))))
  665.         (if (math-realp xvalue)
  666.             (setq xvalue (calcFunc-index numsteps xvalue 1))
  667.           (error "%s is not a suitable basis for %s" xname yname))))
  668.         (if (eq (car-safe y3value) 'vec)
  669.         (or (= (1- (length y3value)) numsteps3)
  670.             (error "%s has wrong length" y3name))
  671.           (if (and (eq (car-safe y3value) 'intv)
  672.                (math-constp y3value))
  673.           (setq y3value (calcFunc-index numsteps3
  674.                         (nth 2 y3value)
  675.                         (math-div
  676.                          (math-sub (nth 3 y3value)
  677.                                (nth 2 y3value))
  678.                          (1- numsteps3))))
  679.         (if (math-realp y3value)
  680.             (setq y3value (calcFunc-index numsteps3 y3value 1))
  681.           (error "%s is not a suitable basis for %s" y3name yname))))
  682.         (setq xp nil
  683.           yp nil
  684.           zp nil
  685.           xvec t)
  686.         (while (setq xvalue (cdr xvalue) yvalue (cdr yvalue))
  687.           (setq xp (nconc xp (make-list (1+ numsteps3) (car xvalue)))
  688.             yp (nconc yp (cons 0 (copy-sequence (cdr y3value))))
  689.             zp (nconc zp (cons '(skip)
  690.                        (copy-sequence (cdr (car yvalue)))))))
  691.         (setq numsteps (1- (* numsteps (1+ numsteps3)))))
  692.     (if (= (setq numsteps (1- (length yvalue))) 0)
  693.         (error "Can't plot an empty vector"))
  694.     (or (and (eq (car-safe xvalue) 'vec)
  695.          (= (1- (length xvalue)) numsteps))
  696.         (error "%s is not a suitable basis for %s" xname yname))
  697.     (or (and (eq (car-safe y3value) 'vec)
  698.          (= (1- (length y3value)) numsteps))
  699.         (error "%s is not a suitable basis for %s" y3name yname))
  700.     (setq xp xvalue
  701.           yp y3value
  702.           zp yvalue
  703.           xvec t))
  704.     (or (math-realp yvalue)
  705.     (let ((arglist nil))
  706.       (setq yvalue (math-evaluate-expr yvalue))
  707.       (calc-default-formula-arglist yvalue)
  708.       (setq arglist (sort arglist 'string-lessp))
  709.       (or (cdr arglist)
  710.           (error "%s does not contain enough unassigned variables" yname))
  711.       (and (cdr (cdr arglist))
  712.            (error "%s contains too many variables: %s" yname arglist))
  713.       (setq yvalue (math-multi-subst yvalue
  714.                      (mapcar 'math-build-var-name
  715.                          arglist)
  716.                      '((var DUMMY var-DUMMY)
  717.                        (var DUMMY2 var-DUMMY2))))))
  718.     (if (setq xvec (eq (car-safe xvalue) 'vec))
  719.     (setq numsteps (1- (length xvalue)))
  720.       (if (and (eq (car-safe xvalue) 'intv)
  721.            (math-constp xvalue))
  722.       (setq numsteps resolution
  723.         xvalue (calcFunc-index numsteps
  724.                        (nth 2 xvalue)
  725.                        (math-div (math-sub (nth 3 xvalue)
  726.                                (nth 2 xvalue))
  727.                          (1- numsteps))))
  728.     (error "%s is not a suitable basis for %s"
  729.            xname yname)))
  730.     (if (setq y3vec (eq (car-safe y3value) 'vec))
  731.     (setq numsteps3 (1- (length y3value)))
  732.       (if (and (eq (car-safe y3value) 'intv)
  733.            (math-constp y3value))
  734.       (setq numsteps3 resolution
  735.         y3value (calcFunc-index numsteps3
  736.                     (nth 2 y3value)
  737.                     (math-div (math-sub (nth 3 y3value)
  738.                                 (nth 2 y3value))
  739.                           (1- numsteps3))))
  740.     (error "%s is not a suitable basis for %s"
  741.            y3name yname)))
  742.     (setq xp nil
  743.       yp nil
  744.       zp nil
  745.       xvec t)
  746.     (setq math-working-step 0)
  747.     (while (setq xvalue (cdr xvalue))
  748.       (setq xp (nconc xp (make-list (1+ numsteps3) (car xvalue)))
  749.         yp (nconc yp (cons 0 (copy-sequence (cdr y3value))))
  750.         zp (cons '(skip) zp)
  751.         y3step y3value
  752.         var-DUMMY (car xvalue)
  753.         math-working-step-2 0
  754.         math-working-step (1+ math-working-step))
  755.       (while (setq y3step (cdr y3step))
  756.     (setq math-working-step-2 (1+ math-working-step-2)
  757.           var-DUMMY2 (car y3step)
  758.           zp (cons (math-evaluate-expr yvalue) zp))))
  759.     (setq zp (nreverse zp)
  760.       numsteps (1- (* numsteps (1+ numsteps3)))))
  761. )
  762.  
  763. (defun calc-graph-format-data ()
  764.   (while (<= (setq stepcount (1+ stepcount)) numsteps)
  765.     (if xvec
  766.     (setq xp (cdr xp)
  767.           xval (car xp)
  768.           yp (cdr yp)
  769.           yval (car yp)
  770.           zp (cdr zp)
  771.           zval (car zp))
  772.       (if yvec
  773.       (setq xval xvalue
  774.         xvalue (math-add xvalue xstep)
  775.         yp (cdr yp)
  776.         yval (car yp))
  777.     (setq xval (car (car yp))
  778.           yval (cdr (car yp))
  779.           yp (cdr yp))
  780.     (if (or (not yp)
  781.         (and xhigh (equal xval xhigh)))
  782.         (setq numsteps 0))))
  783.     (if is-splot
  784.     (if (and (eq (car-safe zval) 'calcFunc-xyz)
  785.          (= (length zval) 4))
  786.         (setq xval (nth 1 zval)
  787.           yval (nth 2 zval)
  788.           zval (nth 3 zval)))
  789.       (if (and (eq (car-safe yval) 'calcFunc-xyz)
  790.            (= (length yval) 4))
  791.       (progn
  792.         (or surprise-splot
  793.         (save-excursion
  794.           (set-buffer (get-buffer-create "*Gnuplot Temp*"))
  795.           (save-excursion
  796.             (goto-char (point-max))
  797.             (re-search-backward "^plot[ \t]")
  798.             (insert "set parametric\ns")
  799.             (setq surprise-splot t))))
  800.         (setq xval (nth 1 yval)
  801.           zval (nth 3 yval)
  802.           yval (nth 2 yval)))
  803.     (if (and (eq (car-safe yval) 'calcFunc-xy)
  804.          (= (length yval) 3))
  805.         (setq xval (nth 1 yval)
  806.           yval (nth 2 yval)))))
  807.     (if (and (Math-realp xval)
  808.          (Math-realp yval)
  809.          (or (not zval) (Math-realp zval)))
  810.     (progn
  811.       (setq blank nil
  812.         non-blank t)
  813.       (if (Math-integerp xval)
  814.           (insert (math-format-number xval))
  815.         (if (eq (car xval) 'frac)
  816.         (setq xval (math-float xval)))
  817.         (insert (math-format-number (nth 1 xval))
  818.             "e" (int-to-string (nth 2 xval))))
  819.       (insert " ")
  820.       (if (Math-integerp yval)
  821.           (insert (math-format-number yval))
  822.         (if (eq (car yval) 'frac)
  823.         (setq yval (math-float yval)))
  824.         (insert (math-format-number (nth 1 yval))
  825.             "e" (int-to-string (nth 2 yval))))
  826.       (if zval
  827.           (progn
  828.         (insert " ")
  829.         (if (Math-integerp zval)
  830.             (insert (math-format-number zval))
  831.           (if (eq (car zval) 'frac)
  832.               (setq zval (math-float zval)))
  833.           (insert (math-format-number (nth 1 zval))
  834.               "e" (int-to-string (nth 2 zval))))))
  835.       (insert "\n"))
  836.       (and (not (equal zval '(skip)))
  837.        (boundp 'var-PlotRejects)
  838.        (eq (car-safe var-PlotRejects) 'vec)
  839.        (nconc var-PlotRejects
  840.           (list (list 'vec
  841.                   curve-num
  842.                   stepcount
  843.                   xval yval)))
  844.        (calc-refresh-evaltos 'var-PlotRejects))
  845.       (or blank
  846.       (progn
  847.         (insert "\n")
  848.         (setq blank t)))))
  849. )
  850.  
  851. (defun calc-temp-file-name (num)
  852.   (while (<= (length calc-graph-file-cache) (1+ num))
  853.     (setq calc-graph-file-cache (nconc calc-graph-file-cache (list nil))))
  854.   (car (or (nth (1+ num) calc-graph-file-cache)
  855.        (setcar (nthcdr (1+ num) calc-graph-file-cache)
  856.            (list (make-temp-name
  857.               (concat calc-gnuplot-tempfile
  858.                   (if (<= num 0)
  859.                       (char-to-string (- ?A num))
  860.                     (int-to-string num))))
  861.              nil))))
  862. )
  863.  
  864. (defun calc-graph-delete-temps ()
  865.   (while calc-graph-file-cache
  866.     (and (car calc-graph-file-cache)
  867.      (file-exists-p (car (car calc-graph-file-cache)))
  868.      (condition-case err
  869.          (delete-file (car (car calc-graph-file-cache)))
  870.        (error nil)))
  871.     (setq calc-graph-file-cache (cdr calc-graph-file-cache)))
  872. )
  873.  
  874. (defun calc-graph-kill-hook ()
  875.   (calc-graph-delete-temps)
  876.   (if calc-graph-prev-kill-hook
  877.       (funcall calc-graph-prev-kill-hook))
  878. )
  879.  
  880. (defun calc-graph-show-tty (output)
  881.   "Default calc-gnuplot-plot-command for \"tty\" output mode.
  882. This is useful for tek40xx and other graphics-terminal types."
  883.   (call-process-region 1 1 shell-file-name
  884.                nil calc-gnuplot-buffer nil
  885.                "-c" (format "cat %s >/dev/tty; rm %s" output output))
  886. )
  887.  
  888. (defun calc-graph-show-dumb (&optional output)
  889.   "Default calc-gnuplot-plot-command for Pinard's \"dumb\" terminal type.
  890. This \"dumb\" driver will be present in Gnuplot 3.0."
  891.   (interactive)
  892.   (save-window-excursion
  893.     (switch-to-buffer calc-gnuplot-buffer)
  894.     (delete-other-windows)
  895.     (goto-char calc-gnuplot-trail-mark)
  896.     (or (search-forward "\f" nil t)
  897.     (sleep-for 1))
  898.     (goto-char (point-max))
  899.     (re-search-backward "\f\\|^[ \t]+\\^$\\|G N U P L O T")
  900.     (setq found-pt (point))
  901.     (if (looking-at "\f")
  902.     (progn
  903.       (forward-char 1)
  904.       (if (eolp) (forward-line 1))
  905.       (or (calc-graph-find-command "time")
  906.           (calc-graph-find-command "title")
  907.           (calc-graph-find-command "ylabel")
  908.           (let ((pt (point)))
  909.         (insert-before-markers (format "(%s)" (current-time-string)))
  910.         (goto-char pt)))
  911.       (set-window-start (selected-window) (point))
  912.       (goto-char (point-max)))
  913.       (end-of-line)
  914.       (backward-char 1)
  915.       (recenter '(4)))
  916.     (or (boundp 'calc-dumb-map)
  917.     (progn
  918.       (setq calc-dumb-map (make-sparse-keymap))
  919.       (define-key calc-dumb-map "\n" 'scroll-up)
  920.       (define-key calc-dumb-map " " 'scroll-up)
  921.       (define-key calc-dumb-map "\177" 'scroll-down)
  922.       (define-key calc-dumb-map "<" 'scroll-left)
  923.       (define-key calc-dumb-map ">" 'scroll-right)
  924.       (define-key calc-dumb-map "{" 'scroll-down)
  925.       (define-key calc-dumb-map "}" 'scroll-up)
  926.       (define-key calc-dumb-map "q" 'exit-recursive-edit)
  927.       (define-key calc-dumb-map "\C-c\C-c" 'exit-recursive-edit)))
  928.     (use-local-map calc-dumb-map)
  929.     (setq truncate-lines t)
  930.     (message "Type `q'%s to return to Calc."
  931.          (if (eq (lookup-key (current-global-map) "\e#") 'calc-dispatch)
  932.             " or `M-# M-#'" ""))
  933.     (recursive-edit)
  934.     (bury-buffer "*Gnuplot Trail*"))
  935. )
  936.  
  937. (defun calc-graph-clear ()
  938.   (interactive)
  939.   (if calc-graph-last-device
  940.       (if (or (equal calc-graph-last-device "x11")
  941.           (equal calc-graph-last-device "X11"))
  942.       (calc-gnuplot-command "set output"
  943.                 (if (equal calc-graph-last-output "STDOUT")
  944.                     ""
  945.                   (prin1-to-string calc-graph-last-output)))
  946.     (calc-gnuplot-command "clear")))
  947. )
  948.  
  949. (defun calc-graph-title-x (title)
  950.   (interactive "sX axis title: ")
  951.   (calc-graph-set-command "xlabel" (if (not (equal title ""))
  952.                        (prin1-to-string title)))
  953. )
  954.  
  955. (defun calc-graph-title-y (title)
  956.   (interactive "sY axis title: ")
  957.   (calc-graph-set-command "ylabel" (if (not (equal title ""))
  958.                        (prin1-to-string title)))
  959. )
  960.  
  961. (defun calc-graph-title-z (title)
  962.   (interactive "sZ axis title: ")
  963.   (calc-graph-set-command "zlabel" (if (not (equal title ""))
  964.                        (prin1-to-string title)))
  965. )
  966.  
  967. (defun calc-graph-range-x (range)
  968.   (interactive "sX axis range: ")
  969.   (calc-graph-set-range "xrange" range)
  970. )
  971.  
  972. (defun calc-graph-range-y (range)
  973.   (interactive "sY axis range: ")
  974.   (calc-graph-set-range "yrange" range)
  975. )
  976.  
  977. (defun calc-graph-range-z (range)
  978.   (interactive "sZ axis range: ")
  979.   (calc-graph-set-range "zrange" range)
  980. )
  981.  
  982. (defun calc-graph-set-range (cmd range)
  983.   (if (equal range "$")
  984.       (calc-wrapper
  985.        (let ((val (calc-top-n 1)))
  986.      (if (and (eq (car-safe val) 'intv) (math-constp val))
  987.          (setq range (concat
  988.               (math-format-number (math-float (nth 2 val))) ":"
  989.               (math-format-number (math-float (nth 3 val)))))
  990.        (if (and (eq (car-safe val) 'vec)
  991.             (= (length val) 3))
  992.            (setq range (concat
  993.                 (math-format-number (math-float (nth 1 val))) ":"
  994.                 (math-format-number (math-float (nth 2 val)))))
  995.          (error "Range specification must be an interval or 2-vector")))
  996.      (calc-pop-stack 1))))
  997.   (if (string-match "\\[.+\\]" range)
  998.       (setq range (substring range 1 -1)))
  999.   (if (and (not (string-match ":" range))
  1000.        (or (string-match "," range)
  1001.            (string-match " " range)))
  1002.       (aset range (match-beginning 0) ?\:))
  1003.   (calc-graph-set-command cmd (if (not (equal range ""))
  1004.                   (concat "[" range "]")))
  1005. )
  1006.  
  1007. (defun calc-graph-log-x (flag)
  1008.   (interactive "P")
  1009.   (calc-graph-set-log flag 0 0)
  1010. )
  1011.  
  1012. (defun calc-graph-log-y (flag)
  1013.   (interactive "P")
  1014.   (calc-graph-set-log 0 flag 0)
  1015. )
  1016.  
  1017. (defun calc-graph-log-z (flag)
  1018.   (interactive "P")
  1019.   (calc-graph-set-log 0 0 flag)
  1020. )
  1021.  
  1022. (defun calc-graph-set-log (xflag yflag zflag)
  1023.   (let* ((old (or (calc-graph-find-command "logscale") ""))
  1024.      (xold (string-match "x" old))
  1025.      (yold (string-match "y" old))
  1026.      (zold (string-match "z" old))
  1027.      str)
  1028.     (setq str (concat (if (if xflag
  1029.                   (if (eq xflag 0) xold
  1030.                 (> (prefix-numeric-value xflag) 0))
  1031.                 (not xold)) "x" "")
  1032.               (if (if yflag
  1033.                   (if (eq yflag 0) yold
  1034.                 (> (prefix-numeric-value yflag) 0))
  1035.                 (not yold)) "y" "")
  1036.               (if (if zflag
  1037.                   (if (eq zflag 0) zold
  1038.                 (> (prefix-numeric-value zflag) 0))
  1039.                 (not zold)) "z" "")))
  1040.     (calc-graph-set-command "logscale" (if (not (equal str "")) str)))
  1041. )
  1042.  
  1043. (defun calc-graph-line-style (style)
  1044.   (interactive "P")
  1045.   (calc-graph-set-styles (and style (prefix-numeric-value style)) t)
  1046. )
  1047.  
  1048. (defun calc-graph-point-style (style)
  1049.   (interactive "P")
  1050.   (calc-graph-set-styles t (and style (prefix-numeric-value style)))
  1051. )
  1052.  
  1053. (defun calc-graph-set-styles (lines points)
  1054.   (calc-graph-init)
  1055.   (save-excursion
  1056.     (set-buffer calc-gnuplot-input)
  1057.     (or (calc-graph-find-plot nil nil)
  1058.     (error "No data points have been set!"))
  1059.     (let ((base (point))
  1060.       (mode nil) (lstyle nil) (pstyle nil)
  1061.       start end lenbl penbl)
  1062.       (re-search-forward "[,\n]")
  1063.       (forward-char -1)
  1064.       (setq end (point) start end)
  1065.       (goto-char base)
  1066.       (if (looking-at "[^,\n]*[^,\n \t]\\([ \t]+with\\)")
  1067.       (progn
  1068.         (setq start (match-beginning 1))
  1069.         (goto-char (match-end 0))
  1070.         (if (looking-at "[ \t]+\\([a-z]+\\)")
  1071.         (setq mode (buffer-substring (match-beginning 1)
  1072.                          (match-end 1))))
  1073.         (if (looking-at "[ \ta-z]+\\([0-9]+\\)")
  1074.         (setq lstyle (string-to-int
  1075.                   (buffer-substring (match-beginning 1)
  1076.                         (match-end 1)))))
  1077.         (if (looking-at "[ \ta-z]+[0-9]+[ \t]+\\([0-9]+\\)")
  1078.         (setq pstyle (string-to-int
  1079.                   (buffer-substring (match-beginning 1)
  1080.                         (match-end 1)))))))
  1081.       (setq lenbl (or (equal mode "lines") (equal mode "linespoints"))
  1082.         penbl (or (equal mode "points") (equal mode "linespoints")))
  1083.       (if lines
  1084.       (or (eq lines t)
  1085.           (setq lstyle lines
  1086.             lenbl (>= lines 0)))
  1087.     (setq lenbl (not lenbl)))
  1088.       (if points
  1089.       (or (eq points t)
  1090.           (setq pstyle points
  1091.             penbl (>= points 0)))
  1092.     (setq penbl (not penbl)))
  1093.       (delete-region start end)
  1094.       (goto-char start)
  1095.       (insert " with "
  1096.           (if lenbl
  1097.           (if penbl "linespoints" "lines")
  1098.         (if penbl "points" "dots")))
  1099.       (if (and pstyle (> pstyle 0))
  1100.       (insert " " (if (and lstyle (> lstyle 0)) (int-to-string lstyle) "1")
  1101.           " " (int-to-string pstyle))
  1102.     (if (and lstyle (> lstyle 0))
  1103.         (insert " " (int-to-string lstyle))))))
  1104.   (calc-graph-view-commands)
  1105. )
  1106.  
  1107. (defun calc-graph-zero-x (flag)
  1108.   (interactive "P")
  1109.   (calc-graph-set-command "noxzeroaxis"
  1110.               (and (if flag
  1111.                    (<= (prefix-numeric-value flag) 0)
  1112.                  (not (calc-graph-find-command "noxzeroaxis")))
  1113.                    " "))
  1114. )
  1115.  
  1116. (defun calc-graph-zero-y (flag)
  1117.   (interactive "P")
  1118.   (calc-graph-set-command "noyzeroaxis"
  1119.               (and (if flag
  1120.                    (<= (prefix-numeric-value flag) 0)
  1121.                  (not (calc-graph-find-command "noyzeroaxis")))
  1122.                    " "))
  1123. )
  1124.  
  1125. (defun calc-graph-name (name)
  1126.   (interactive "sTitle for current curve: ")
  1127.   (calc-graph-init)
  1128.   (save-excursion
  1129.     (set-buffer calc-gnuplot-input)
  1130.     (or (calc-graph-find-plot nil nil)
  1131.     (error "No data points have been set!"))
  1132.     (let ((base (point))
  1133.       start)
  1134.       (re-search-forward "[,\n]\\|[ \t]+with")
  1135.       (setq end (match-beginning 0))
  1136.       (goto-char base)
  1137.       (if (looking-at "[^,\n]*[^,\n \t]\\([ \t]+title\\)")
  1138.       (progn
  1139.         (goto-char (match-beginning 1))
  1140.         (delete-region (point) end))
  1141.     (goto-char end))
  1142.       (insert " title " (prin1-to-string name))))
  1143.   (calc-graph-view-commands)
  1144. )
  1145.  
  1146. (defun calc-graph-hide (flag)
  1147.   (interactive "P")
  1148.   (calc-graph-init)
  1149.   (and (calc-graph-find-plot nil nil)
  1150.        (progn
  1151.      (or (looking-at "{")
  1152.          (error "Can't hide this curve (wrong format)"))
  1153.      (forward-char 1)
  1154.      (if (looking-at "*")
  1155.          (if (or (null flag) (<= (prefix-numeric-value flag) 0))
  1156.          (delete-char 1))
  1157.        (if (or (null flag) (> (prefix-numeric-value flag) 0))
  1158.            (insert "*")))))
  1159. )
  1160.  
  1161. (defun calc-graph-header (title)
  1162.   (interactive "sTitle for entire graph: ")
  1163.   (calc-graph-set-command "title" (if (not (equal title ""))
  1164.                       (prin1-to-string title)))
  1165. )
  1166.  
  1167. (defun calc-graph-border (flag)
  1168.   (interactive "P")
  1169.   (calc-graph-set-command "noborder"
  1170.               (and (if flag
  1171.                    (<= (prefix-numeric-value flag) 0)
  1172.                  (not (calc-graph-find-command "noborder")))
  1173.                    " "))
  1174. )
  1175.  
  1176. (defun calc-graph-grid (flag)
  1177.   (interactive "P")
  1178.   (calc-graph-set-command "grid" (and (if flag
  1179.                       (> (prefix-numeric-value flag) 0)
  1180.                     (not (calc-graph-find-command "grid")))
  1181.                       " "))
  1182. )
  1183.  
  1184. (defun calc-graph-key (flag)
  1185.   (interactive "P")
  1186.   (calc-graph-set-command "key" (and (if flag
  1187.                      (> (prefix-numeric-value flag) 0)
  1188.                        (not (calc-graph-find-command "key")))
  1189.                      " "))
  1190. )
  1191.  
  1192. (defun calc-graph-num-points (res flag)
  1193.   (interactive "sNumber of data points: \nP")
  1194.   (if flag
  1195.       (if (> (prefix-numeric-value flag) 0)
  1196.       (if (equal res "")
  1197.           (message "Default resolution is %d."
  1198.                calc-graph-default-resolution)
  1199.         (setq calc-graph-default-resolution (string-to-int res)))
  1200.     (if (equal res "")
  1201.         (message "Default 3D resolution is %d."
  1202.              calc-graph-default-resolution-3d)
  1203.       (setq calc-graph-default-resolution-3d (string-to-int res))))
  1204.     (calc-graph-set-command "samples" (if (not (equal res "")) res)))
  1205. )
  1206.  
  1207. (defun calc-graph-device (name flag)
  1208.   (interactive "sDevice name: \nP")
  1209.   (if (equal name "?")
  1210.       (progn
  1211.     (calc-gnuplot-command "set terminal")
  1212.     (calc-graph-view-trail))
  1213.     (if flag
  1214.     (if (> (prefix-numeric-value flag) 0)
  1215.         (if (equal name "")
  1216.         (message "Default GNUPLOT device is \"%s\"."
  1217.              calc-gnuplot-default-device)
  1218.           (setq calc-gnuplot-default-device name))
  1219.       (if (equal name "")
  1220.           (message "GNUPLOT device for Print command is \"%s\"."
  1221.                calc-gnuplot-print-device)
  1222.         (setq calc-gnuplot-print-device name)))
  1223.       (calc-graph-set-command "terminal" (if (not (equal name ""))
  1224.                          name))))
  1225. )
  1226.  
  1227. (defun calc-graph-output (name flag)
  1228.   (interactive "FOutput file name: \np")
  1229.   (cond ((string-match "\\<[aA][uU][tT][oO]$" name)
  1230.      (setq name "auto"))
  1231.     ((string-match "\\<[tT][tT][yY]$" name)
  1232.      (setq name "tty"))
  1233.     ((string-match "\\<[sS][tT][dD][oO][uU][tT]$" name)
  1234.      (setq name "STDOUT"))
  1235.     ((equal (file-name-nondirectory name) "")
  1236.      (setq name ""))
  1237.     (t (setq name (expand-file-name name))))
  1238.   (if flag
  1239.       (if (> (prefix-numeric-value flag) 0)
  1240.       (if (equal name "")
  1241.           (message "Default GNUPLOT output file is \"%s\"."
  1242.                calc-gnuplot-default-output)
  1243.         (setq calc-gnuplot-default-output name))
  1244.     (if (equal name "")
  1245.         (message "GNUPLOT output file for Print command is \"%s\"."
  1246.              calc-gnuplot-print-output)
  1247.       (setq calc-gnuplot-print-output name)))
  1248.     (calc-graph-set-command "output" (if (not (equal name ""))
  1249.                      (prin1-to-string name))))
  1250. )
  1251.  
  1252. (defun calc-graph-display (name)
  1253.   (interactive "sX display name: ")
  1254.   (if (equal name "")
  1255.       (message "Current X display is \"%s\"."
  1256.            (or calc-gnuplot-display "<none>"))
  1257.     (setq calc-gnuplot-display name)
  1258.     (if (calc-gnuplot-alive)
  1259.     (calc-gnuplot-command "exit")))
  1260. )
  1261.  
  1262. (defun calc-graph-geometry (name)
  1263.   (interactive "sX geometry spec (or \"default\"): ")
  1264.   (if (equal name "")
  1265.       (message "Current X geometry is \"%s\"."
  1266.            (or calc-gnuplot-geometry "default"))
  1267.     (setq calc-gnuplot-geometry (and (not (equal name "default")) name))
  1268.     (if (calc-gnuplot-alive)
  1269.     (calc-gnuplot-command "exit")))
  1270. )
  1271.  
  1272. (defun calc-graph-find-command (cmd)
  1273.   (calc-graph-init)
  1274.   (save-excursion
  1275.     (set-buffer calc-gnuplot-input)
  1276.     (goto-char (point-min))
  1277.     (if (re-search-forward (concat "^set[ \t]+" cmd "[ \t]*\\(.*\\)$") nil t)
  1278.     (buffer-substring (match-beginning 1) (match-end 1))))
  1279. )
  1280.  
  1281. (defun calc-graph-set-command (cmd &rest args)
  1282.   (calc-graph-init)
  1283.   (save-excursion
  1284.     (set-buffer calc-gnuplot-input)
  1285.     (goto-char (point-min))
  1286.     (if (re-search-forward (concat "^set[ \t]+" cmd "[ \t\n]") nil t)
  1287.     (progn
  1288.       (forward-char -1)
  1289.       (end-of-line)
  1290.       (let ((end (point)))
  1291.         (beginning-of-line)
  1292.         (delete-region (point) (1+ end))))
  1293.       (if (calc-graph-find-plot t t)
  1294.       (if (eq (preceding-char) ?\n)
  1295.           (forward-char -1))
  1296.     (goto-char (1- (point-max)))))
  1297.     (if (and args (car args))
  1298.     (progn
  1299.       (or (bolp)
  1300.           (insert "\n"))
  1301.       (insert "set " (mapconcat 'identity (cons cmd args) " ") "\n"))))
  1302.   (calc-graph-view-commands)
  1303. )
  1304.  
  1305. (defun calc-graph-command (cmd)
  1306.   (interactive "sGNUPLOT command: ")
  1307.   (calc-wrapper
  1308.    (calc-graph-init)
  1309.    (calc-graph-view-trail)
  1310.    (calc-gnuplot-command cmd)
  1311.    (accept-process-output)
  1312.    (calc-graph-view-trail))
  1313. )
  1314.  
  1315. (defun calc-graph-kill (&optional no-view)
  1316.   (interactive)
  1317.   (calc-graph-delete-temps)
  1318.   (if (calc-gnuplot-alive)
  1319.       (calc-wrapper
  1320.        (or no-view (calc-graph-view-trail))
  1321.        (let ((calc-graph-no-wait t))
  1322.      (calc-gnuplot-command "exit"))
  1323.        (sit-for 1)
  1324.        (if (process-status calc-gnuplot-process)
  1325.        (delete-process calc-gnuplot-process))
  1326.        (setq calc-gnuplot-process nil)))
  1327. )
  1328.  
  1329. (defun calc-graph-quit ()
  1330.   (interactive)
  1331.   (if (get-buffer-window calc-gnuplot-input)
  1332.       (calc-graph-view-commands t))
  1333.   (if (get-buffer-window calc-gnuplot-buffer)
  1334.       (calc-graph-view-trail t))
  1335.   (calc-graph-kill t)
  1336. )
  1337.  
  1338. (defun calc-graph-view-commands (&optional no-need)
  1339.   (interactive "p")
  1340.   (or calc-graph-no-auto-view (calc-graph-init-buffers))
  1341.   (calc-graph-view calc-gnuplot-input calc-gnuplot-buffer (null no-need))
  1342. )
  1343.  
  1344. (defun calc-graph-view-trail (&optional no-need)
  1345.   (interactive "p")
  1346.   (or calc-graph-no-auto-view (calc-graph-init-buffers))
  1347.   (calc-graph-view calc-gnuplot-buffer calc-gnuplot-input (null no-need))
  1348. )
  1349.  
  1350. (defun calc-graph-view (buf other-buf need)
  1351.   (let (win)
  1352.     (or calc-graph-no-auto-view
  1353.     (if (setq win (get-buffer-window buf))
  1354.         (or need
  1355.         (and (eq buf calc-gnuplot-buffer)
  1356.              (save-excursion
  1357.                (set-buffer buf)
  1358.                (not (pos-visible-in-window-p (point-max) win))))
  1359.         (progn
  1360.           (bury-buffer buf)
  1361.           (bury-buffer other-buf)
  1362.           (let ((curwin (selected-window)))
  1363.             (select-window win)
  1364.             (switch-to-buffer nil)
  1365.             (select-window curwin))))
  1366.       (if (setq win (get-buffer-window other-buf))
  1367.           (set-window-buffer win buf)
  1368.         (if (eq major-mode 'calc-mode)
  1369.         (if (or need
  1370.             (< (window-height) (1- (screen-height))))
  1371.             (display-buffer buf))
  1372.           (switch-to-buffer buf)))))
  1373.     (save-excursion
  1374.       (set-buffer buf)
  1375.       (if (and (eq buf calc-gnuplot-buffer)
  1376.            (setq win (get-buffer-window buf))
  1377.            (not (pos-visible-in-window-p (point-max) win)))
  1378.       (progn
  1379.         (goto-char (point-max))
  1380.         (vertical-motion (- 6 (window-height win)))
  1381.         (set-window-start win (point))
  1382.         (goto-char (point-max)))))
  1383.     (or calc-graph-no-auto-view (sit-for 0)))
  1384. )
  1385. (setq calc-graph-no-auto-view nil)
  1386.  
  1387. (defun calc-gnuplot-check-for-errors ()
  1388.   (if (save-excursion
  1389.     (prog2
  1390.      (progn
  1391.        (set-buffer calc-gnuplot-buffer)
  1392.        (goto-char calc-gnuplot-last-error-pos))
  1393.      (re-search-forward "^[ \t]+\\^$" nil t)
  1394.      (goto-char (point-max))
  1395.      (setq calc-gnuplot-last-error-pos (point-max))))
  1396.       (calc-graph-view-trail))
  1397. )
  1398.  
  1399. (defun calc-gnuplot-command (&rest args)
  1400.   (calc-graph-init)
  1401.   (let ((cmd (concat (mapconcat 'identity args " ") "\n")))
  1402.     (accept-process-output)
  1403.     (save-excursion
  1404.       (set-buffer calc-gnuplot-buffer)
  1405.       (calc-gnuplot-check-for-errors)
  1406.       (goto-char (point-max))
  1407.       (setq calc-gnuplot-trail-mark (point))
  1408.       (or (>= calc-gnuplot-version 3)
  1409.       (insert cmd))
  1410.       (set-marker (process-mark calc-gnuplot-process) (point))
  1411.       (process-send-string calc-gnuplot-process cmd)
  1412.       (if (get-buffer-window calc-gnuplot-buffer)
  1413.       (calc-graph-view-trail))
  1414.       (accept-process-output (and (not calc-graph-no-wait)
  1415.                   calc-gnuplot-process))
  1416.       (calc-gnuplot-check-for-errors)
  1417.       (if (get-buffer-window calc-gnuplot-buffer)
  1418.       (calc-graph-view-trail))))
  1419. )
  1420. (setq calc-graph-no-wait nil)
  1421.  
  1422. (defun calc-graph-init-buffers ()
  1423.   (or (and calc-gnuplot-buffer
  1424.        (buffer-name calc-gnuplot-buffer))
  1425.       (setq calc-gnuplot-buffer (get-buffer-create "*Gnuplot Trail*")))
  1426.   (or (and calc-gnuplot-input
  1427.        (buffer-name calc-gnuplot-input))
  1428.       (setq calc-gnuplot-input (get-buffer-create "*Gnuplot Commands*")))
  1429. )
  1430.  
  1431. (defun calc-graph-init ()
  1432.   (or (calc-gnuplot-alive)
  1433.       (let ((process-connection-type t)
  1434.         origin)
  1435.     (if calc-gnuplot-process
  1436.         (progn
  1437.           (delete-process calc-gnuplot-process)
  1438.           (setq calc-gnuplot-process nil)))
  1439.     (calc-graph-init-buffers)
  1440.     (save-excursion
  1441.       (set-buffer calc-gnuplot-buffer)
  1442.       (insert "\nStarting gnuplot...\n")
  1443.       (setq origin (point)))
  1444.     (setq calc-graph-last-device nil)
  1445.     (setq calc-graph-last-output nil)
  1446.     (condition-case err
  1447.         (let ((args (append (and calc-gnuplot-display
  1448.                      (not (equal calc-gnuplot-display
  1449.                          (getenv "DISPLAY")))
  1450.                      (list "-display"
  1451.                        calc-gnuplot-display))
  1452.                 (and calc-gnuplot-geometry
  1453.                      (list "-geometry"
  1454.                        calc-gnuplot-geometry)))))
  1455.           (setq calc-gnuplot-process 
  1456.             (apply 'start-process
  1457.                "gnuplot"
  1458.                calc-gnuplot-buffer
  1459.                calc-gnuplot-name
  1460.                args))
  1461.           (process-kill-without-query calc-gnuplot-process))
  1462.       (file-error
  1463.        (error "Sorry, can't find \"%s\" on your system."
  1464.           calc-gnuplot-name)))
  1465.     (save-excursion
  1466.       (set-buffer calc-gnuplot-buffer)
  1467.       (while (and (not (save-excursion
  1468.                  (goto-char origin)
  1469.                  (search-forward "gnuplot> " nil t)))
  1470.               (memq (process-status calc-gnuplot-process) '(run stop)))
  1471.         (accept-process-output calc-gnuplot-process))
  1472.       (or (memq (process-status calc-gnuplot-process) '(run stop))
  1473.           (error "Unable to start GNUPLOT process."))
  1474.       (if (save-excursion
  1475.         (goto-char origin)
  1476.         (re-search-forward
  1477.          "G N U P L O T.*\n.*version \\([0-9]+\\)\\." nil t))
  1478.           (setq calc-gnuplot-version (string-to-int (buffer-substring
  1479.                              (match-beginning 1)
  1480.                              (match-end 1))))
  1481.         (setq calc-gnuplot-version 1))
  1482.       (goto-char (point-max)))))
  1483.   (save-excursion
  1484.     (set-buffer calc-gnuplot-input)
  1485.     (if (= (buffer-size) 0)
  1486.     (insert "# Commands for running gnuplot\n\n\n")
  1487.       (or calc-graph-no-auto-view
  1488.       (eq (char-after (1- (point-max))) ?\n)
  1489.       (progn
  1490.         (goto-char (point-max))
  1491.         (insert "\n")))))
  1492. )
  1493.  
  1494.